using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Configuration;
using System.Xml;
using System.Web;
using System.IO;

using OrbitOne.Feed.Domain;
using OrbitOne.Feed.Interfaces;

namespace OrbitOne.Feed.Handlers {
    /// <summary>
    /// Writes RSS 2.0 formatted xml in the http outputstream.
    /// RSS is an acronym for Really Simple Syndication.
    /// </summary>
    internal class RSSWriter : AbstractWriter {
        #region Members :
        static CultureInfo _usCultureInfo = CultureInfo.CreateSpecificCulture("en-us");
        //const String _dateTimeFormat = @"ddd, dd MMM yyyy 00:00:00 G\MT";
        const String _dateTimeFormat = "R";
        #endregion Members 
        #region Ctor's :
        public RSSWriter(WebFeed webFeed) : base(webFeed) {
        }
        #endregion Ctor's
        #region Methods :
        /// <summary>
        /// Writes the actual feed in to the Http output stream.
        /// This method must be implemented by specific Writers like the Atom, RSS or podcast writers.
        /// </summary>
        /// <param name="webFeed">The web feed.</param>
        public override void WriteFeed() {
            BeginWriteFeedInfo();
            foreach (Topic topic in webFeed.Topics) {
                WriteTopic(topic);
            }
            EndWriteFeedInfo();
        }
        /// <summary>
        /// Writes the feed info.
        /// </summary>
        /// <param name="webFeed">The web feed.</param>
        protected virtual void BeginWriteFeedInfo() {
            WriteFeedRootElement();
            WriteRootAttributes();
            _writer.WriteStartElement("channel");
            this.WriteFeedTitle();
            this.WriteFeedLastUpdated(); 
            this.WriteFeedUrl();
            this.WriteFeedDescription();
            base.WriteElementValue("language", webFeed.Culture.Name.ToLower());
            this.WriteCopyright();
        }
        /// <summary>
        /// Closes the opened feed info xml elements.
        /// </summary>
        private void EndWriteFeedInfo() {
            _writer.WriteEndElement(); // end channel 
            _writer.WriteEndElement(); // end rss
            _writer.Flush();
        }
        /// <summary>
        /// Write topic extensions
        /// </summary>
        protected virtual void WriteTopicExtentions(Topic topic) {
        }
        #region Implementation Abstract methods :
        /// <summary>
        /// Writes the root element
        /// </summary>
        protected override void WriteFeedRootElement() {
            _writer.WriteStartElement("rss");
        }
        /// <summary>
        /// Writes the copyright text.
        /// </summary>
        protected override void WriteCopyright() {
            base.WriteElementValue("copyright", webFeed.Copyright);
        }
        /// <summary>
        /// Writes the last update date time of the feed
        /// </summary>
        protected override void WriteFeedLastUpdated() {
            base.WriteElementValue("pubDate", DateTime.Now.ToString(_dateTimeFormat, _usCultureInfo.DateTimeFormat));
        }
        /// <summary>
        /// Writes the feed's link
        /// </summary>
        protected override void WriteFeedUrl() {
            base.WriteElementValue("link", webFeed.Url.ToString());
        }
        /// <summary>
        /// Writes the root attributes.
        /// </summary>
        protected override void WriteRootAttributes() {
            WriteAttributeValue("version", "2.0");
        }
        /// <summary>
        /// Writes the topic info.
        /// </summary>
        /// <param name="topic">The topic.</param>
        protected override void WriteTopic(Topic topic) {
            _writer.WriteStartElement("item");
            this.WriteTopicIdentification(topic);
            base.WriteElementValue("title", topic.Title);
            base.WriteElementValue("link", topic.Url.ToString());
            base.WriteElementValue("description", topic.Description);
            this.WriteTopicCategories(topic);
            this.WriteTopicPublishDateTime(topic);
            this.WriteTopicAuthor(topic);
            this.WriteTopicContent(topic);
            this.WriteTopicExtentions(topic);
            _writer.WriteEndElement();
        }
        /// <summary>
        /// Writes the publish date time.
        /// </summary>
        /// <param name="topic">The topic.</param>
        protected override void WriteTopicPublishDateTime(Topic topic) {
            String dateTimeString = topic.PublishDateTime.ToString(_dateTimeFormat, _usCultureInfo.DateTimeFormat);
            base.WriteElementValue("pubDate", dateTimeString);
        }
        /// <summary>
        /// Writes the topic identification.
        /// </summary>
        /// <param name="topic">The topic.</param>
        protected override void WriteTopicIdentification(Topic topic) {
            _writer.WriteStartElement("guid");
            WriteAttributeValue("isPermaLink", "false");
            _writer.WriteValue(topic.Id);
            _writer.WriteEndElement();
        }
        /// <summary>
        /// Writes the categories.
        /// </summary>
        /// <param name="topic">The topic.</param>
        protected override void WriteTopicCategories(Topic topic) {
            foreach (Category category in topic.Categories) {
                _writer.WriteStartElement("category");
                if (category.HasDomain) {
                    WriteAttributeValue("domain", category.Domain.ToString());
                }
                _writer.WriteValue(category.Name);
                _writer.WriteEndElement();
            }
        }
        /// <summary>
        /// Writes the content.
        /// </summary>
        /// <param name="topic">The topic.</param>
        protected override void WriteTopicContent(Topic topic) {
            if (topic.HasContent) {
                base._writer.WriteStartElement("enclosure");
                base.WriteAttributeValue("url", topic.Content.Url.ToString());
                base.WriteAttributeValue("length", topic.Content.Length.ToString());
                base.WriteAttributeValue("type", topic.Content.MimeType.ToString());
                base._writer.WriteEndElement();
            }
        }
        /// <summary>
        /// Writes the topic author.
        /// </summary>
        /// <param name="topic">The topic.</param>
        protected override void WriteTopicAuthor(Topic topic) {
            if (topic.HasAuthor) {
                base.WriteElementValue("author", topic.Author.Email);
            }
        }
        /// <summary>
        /// Writes the feed author
        /// </summary>
        protected override void WriteFeedAuthor() {
            base.WriteElementValue("managingEditor", webFeed.Author.Email);
        }
        /// <summary>
        /// Writes the feed description
        /// </summary>
        protected override void WriteFeedDescription() {
            base.WriteElementValue("description", webFeed.Description);
        }
        /// <summary>
        /// Writes the feed's title to the Http Ouput stream.
        /// </summary>
        protected override void WriteFeedTitle() {
            base.WriteElementValue("title", webFeed.Title);
        }
        #endregion Implementation Abstract methods :
        #endregion Methods
    }
}
